package com.wl.wuliu.utils;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author Mr.Gu
 * @date 2020/9/5 13:36
 * @function :  处理日期工具类
 **/
public class DateUtils {

    /**
     * 时间格式(yyyy-MM-dd)
     */
    public final static String DATE_PATTERN = "yyyy-MM-dd";
    /**
     * 时间格式(yyyy-MM-dd HH:mm:ss)
     */
    public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    public final static long dayms = 1000 * 24 * 60 * 60;// 一天的毫秒数
    public final static long hourms = 1000 * 60 * 60;// 一小时的毫秒数

    /**
     * 将日期时间转为corn
     * @param date 要转换的日期，传该参数则会得到当前时间对应的corn
     * @return  得到的corn表达式
     */
    public static String dateToCorn(String date) {
        String corn = null;
        SimpleDateFormat sdf = new SimpleDateFormat("ss mm HH dd MM ?");
        try {
            if (StringUtils.isNotEmpty(date)) {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date parse = simpleDateFormat.parse(date);
                if (Objects.nonNull(parse)) {
                    corn = sdf.format(parse);
                }
            }else {
                corn = sdf.format(new Date());
            }
            return corn;
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将日期时间转为corn
     * @param date 要转换的日期，不传该参数则会得到当前时间对应的corn
     * @return  得到的corn表达式
     */
    public static String dateToCorn(Date date) {
        String corn = null;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("ss mm HH dd MM ?");
            if (Objects.nonNull(date)) {
                corn = sdf.format(date);
            }else {
                corn = sdf.format(new Date());
            }
            return corn;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 日期格式化 日期格式为：yyyy-MM-dd
     *
     * @param date 日期
     * @return 返回yyyy-MM-dd格式日期
     */
    public static String format(Date date) {
        return format(date, DATE_PATTERN);
    }

    /**
     * PHP时间戳转化为日期
     * @param timeStamp
     * @return yyyy-MM-dd HH:mm:ss
     */
    public static String PHPformat(long timeStamp) {
        Date date = new Date(timeStamp * 1000L);
        return format(date, DATE_TIME_PATTERN);
    }

    /**
     * 日期格式化 日期格式为：yyyy-MM-dd
     * @param date    日期
     * @param pattern 格式，如：DateUtils.DATE_TIME_PATTERN
     * @return 返回yyyy-MM-dd格式日期
     */
    public static String format(Date date, String pattern) {
        if (date != null) {
            SimpleDateFormat df = new SimpleDateFormat(pattern);
            return df.format(date);
        }
        return null;
    }

    /**
     * 字符串转换成日期
     * @param strDate 日期字符串
     * @param pattern 日期的格式，如：DateUtils.DATE_TIME_PATTERN
     */
    public static Date stringToDate(String strDate, String pattern) {
        if (StringUtils.isBlank(strDate)) {
            return null;
        }
        DateTimeFormatter fmt = DateTimeFormat.forPattern(pattern);
        return fmt.parseLocalDateTime(strDate).toDate();
    }

    /**
     * 根据周数，获取开始日期、结束日期
     * @param week 周期  0本周，-1上周，-2上上周，1下周，2下下周
     * @return 返回date[0]开始日期、date[1]结束日期
     */
    public static Date[] getWeekStartAndEnd(int week) {
        DateTime dateTime = new DateTime();
        LocalDate date = new LocalDate(dateTime.plusWeeks(week));

        date = date.dayOfWeek().withMinimumValue();
        Date beginDate = date.toDate();
        Date endDate = date.plusDays(6).toDate();
        return new Date[]{beginDate, endDate};
    }

    /**
     * 对日期的【秒】进行加/减
     *
     * @param date    日期
     * @param seconds 秒数，负数为减
     * @return 加/减几秒后的日期
     */
    public static Date addDateSeconds(Date date, int seconds) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusSeconds(seconds).toDate();
    }

    /**
     * 对日期的【分钟】进行加/减
     *
     * @param date    日期
     * @param minutes 分钟数，负数为减
     * @return 加/减几分钟后的日期
     */
    public static Date addDateMinutes(Date date, int minutes) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusMinutes(minutes).toDate();
    }

    /**
     * 对日期的【小时】进行加/减
     *
     * @param date  日期
     * @param hours 小时数，负数为减
     * @return 加/减几小时后的日期
     */
    public static Date addDateHours(Date date, int hours) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusHours(hours).toDate();
    }

    /**
     * 对日期的【天】进行加/减
     *
     * @param date 日期
     * @param days 天数，负数为减
     * @return 加/减几天后的日期
     */
    public static Date addDateDays(Date date, int days) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusDays(days).toDate();
    }

    /**
     * 对日期的【周】进行加/减
     *
     * @param date  日期
     * @param weeks 周数，负数为减
     * @return 加/减几周后的日期
     */
    public static Date addDateWeeks(Date date, int weeks) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusWeeks(weeks).toDate();
    }

    /**
     * 对日期的【月】进行加/减
     *
     * @param date   日期
     * @param months 月数，负数为减
     * @return 加/减几月后的日期
     */
    public static Date addDateMonths(Date date, int months) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusMonths(months).toDate();
    }

    /**
     * 对日期的【年】进行加/减
     *
     * @param date  日期
     * @param years 年数，负数为减
     * @return 加/减几年后的日期
     */
    public static Date addDateYears(Date date, int years) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusYears(years).toDate();
    }

    //判断选择的日期是否是本周
    public static boolean isThisWeek(long time) {
        Calendar calendar = Calendar.getInstance();
        int currentWeek = calendar.get(Calendar.WEEK_OF_YEAR);
        calendar.setTime(new Date(time));
        int paramWeek = calendar.get(Calendar.WEEK_OF_YEAR);
        if (paramWeek == currentWeek) {
            return true;
        }
        return false;
    }

    //判断选择的日期是否是今天
    public static boolean isToday(long time) {
        return isThisTime(time, "yyyy-MM-dd");
    }

    //判断选择的日期是否是本月
    public static boolean isThisMonth(long time) {
        return isThisTime(time, "yyyy-MM");
    }

    private static boolean isThisTime(long time, String pattern) {
        Date date = new Date(time);
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        String param = sdf.format(date);//参数时间
        String now = sdf.format(new Date());//当前时间
        if (param.equals(now)) {
            return true;
        }
        return false;
    }

    /*
     * @Description: 根据传入的年份确定那天的天数，0为本年
     * @Param: [year]
     * @Return: int
     */
    public static int getdaysNumOfYear(int year) {
        if (year == 0) {
            return java.time.LocalDate.now().lengthOfYear();
        } else {
            return java.time.LocalDate.of(year, 1, 1).lengthOfYear();
        }
    }

    /**
     * 获取传入时间同一天的指定时分秒,并且毫秒数是0的时间
     * @return
     */
    public static Date getDateOfDay(Date date,int hour, int minute , int second){
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.HOUR_OF_DAY, hour);
        c.set(Calendar.MINUTE, minute);
        c.set(Calendar.SECOND, second);
        c.set(Calendar.MILLISECOND, 0);
        Date returnDate = c.getTime();
        return returnDate;
    }
    /**
     * 获取当天的指定时分秒,并且毫秒数是0的时间
     * @return
     */
    public static Date getDateOfCurrentDay(int hour, int minute , int second) {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.HOUR_OF_DAY, hour);
        c.set(Calendar.MINUTE, minute);
        c.set(Calendar.SECOND, second);
        c.set(Calendar.MILLISECOND, 0);
        Date returnDate = c.getTime();
        return returnDate;
    }

    /**
     * 得到格式化后的当月第1天，格式为yyyy-MM-dd，如2006-02-01
     *
     * @param inputDate 要格式化的日期
     * @return
     */
    public static String getFirstDayOfMonth(Date inputDate) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(inputDate);
        int firstDay = cal.getActualMinimum(Calendar.DAY_OF_MONTH);
        cal.set(Calendar.DAY_OF_MONTH, firstDay);
        return format(cal.getTime(), DateUtils.DATE_PATTERN);
    }

    /**
     * 得到格式化后的当月最后1天，格式为yyyy-MM-dd，如2006-02-01
     */
    public static String getLastDayOfMonth(Date inputDate) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(inputDate);
        int firstDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
        cal.set(Calendar.DAY_OF_MONTH, firstDay);
        return format(cal.getTime(), DateUtils.DATE_PATTERN);
    }

    /**
     * 传入一个时间获得 周一到周日的日期
     * @param date
     * @return   map   周一 monday   周日week
     */
    public static Map<String,String> getWeekDate(Date date) {
        Map<String, String> map = new HashMap<>();
        try {
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); //设置时间格式
            Calendar cal = Calendar.getInstance();

            cal.setTime(date);
            //System.out.println("要计算日期为:"+sdf.format(cal.getTime())); //输出要计算日期
            //判断要计算的日期是否是周日，如果是则减一天计算周六的，否则会出问题，计算到下一周去了
            int dayWeek = cal.get(Calendar.DAY_OF_WEEK);//获得当前日期是一个星期的第几天
            if(1 == dayWeek) {
                cal.add(Calendar.DAY_OF_MONTH, -1);
            }
            cal.setFirstDayOfWeek(Calendar.MONDAY);//设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
            int day = cal.get(Calendar.DAY_OF_WEEK);//获得当前日期是一个星期的第几天
            cal.add(Calendar.DATE, cal.getFirstDayOfWeek()-day);//根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
            //System.out.println("所在周星期一的日期："+sdf.format(cal.getTime()));
            map.put("monday",sdf.format(cal.getTime()));
            //System.out.println(cal.getFirstDayOfWeek()+"-"+day+"+6="+(cal.getFirstDayOfWeek()-day+6));
            cal.add(Calendar.DATE, 6);
            //System.out.println("所在周星期日的日期："+sdf.format(cal.getTime()));
            map.put("week",sdf.format(cal.getTime()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

}
